package execute

import (
	"context"
	"fmt"
	"net"
	"net/http"
	"net/url"
	"sieve_engine/lib/config"
	"sieve_engine/lib/log"
	"sieve_engine/proxy"
	"strings"
	"sync/atomic"
	"time"
)

type TransportConfig struct {
	MaxConnCount     int    `json:"max_conn_count"`
	MaxIdleConnCount int    `json:"max_idle_conn_count"`
	SysInterfaces    string `json:"sys_interfaces"`
}

var (
	proxyEnable = *config.Bool("sieve.proxy.enable", true, "proxy enable")
	proxyDebug  = *config.Bool("sieve.proxy.debug", true, "proxy debug")
	transConfig = &TransportConfig{
		MaxConnCount:     *config.Int("sieve.transport.max_conn_count", 50, "transport max_conn_count"),
		MaxIdleConnCount: *config.Int("sieve.transport.max_idle_conn_count", 50, "transport max_idle_conn_count"),
		SysInterfaces:    *config.String("sieve.transport.sys.interfaces", "eno1,eno2,eno3,eno4", "transport sys interfaces"),
	}
	localIpList     []string
	sysInterfaceMap = map[string]struct{}{}

	ipIndex atomic.Int32
)

func init() {
	getSystemInterface()
	SetDefaultTransport("", DefaultNetWorkConfig{}.GetNetWorkConfig())
}

func GetLocalIP() {

}
func getSystemInterface() {

	if transConfig.SysInterfaces == "" {
		return
	}
	for _, v := range strings.Split(transConfig.SysInterfaces, ",") {
		sysInterfaceMap[v] = struct{}{}
	}

	ifAces, err := net.Interfaces()
	if err != nil {
		panic(err)
	}
	for _, iface := range ifAces {
		if _, ok := sysInterfaceMap[iface.Name]; !ok {
			continue
		}

		if _, err := net.InterfaceByName(iface.Name); err != nil {
			panic(err)
		} else {
			addrs, _ := iface.Addrs()
			for _, addr := range addrs {
				if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
					if ipnet.IP.To4() != nil {
						localIp := ipnet.IP.String()
						localIpList = append(localIpList, localIp)
					}
				}
			}
		}
	}
}

func SetDefaultTransport(country string, workConfig *NetWorkConfig) (http.RoundTripper, *url.URL) {

	timeout := workConfig.TransPortConfig.DialTimeOut
	n := &net.Dialer{
		Timeout:   timeout,
		KeepAlive: workConfig.TransPortConfig.DialKeepAlive,
	}

	transport := &http.Transport{
		DialContext:           n.DialContext,
		IdleConnTimeout:       workConfig.TransPortConfig.IdleConnTimeout,
		ExpectContinueTimeout: workConfig.TransPortConfig.ExpectContinueTimeout,
		TLSHandshakeTimeout:   workConfig.TransPortConfig.TLSHandshakeTimeout,
		MaxIdleConns:          transConfig.MaxIdleConnCount,
		MaxConnsPerHost:       transConfig.MaxConnCount,
		MaxIdleConnsPerHost:   transConfig.MaxIdleConnCount,
		DisableKeepAlives:     workConfig.TransPortConfig.DisableKeepAlives,
		TLSClientConfig:       workConfig.TransPortConfig.TLSClientConfig,
	}

	if len(localIpList) > 0 {

		var (
			localIpAddr = localIpList[int(ipIndex.Add(1))%len(localIpList)]
		)

		// transport.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
		//	localAddr := &net.TCPAddr{
		//		IP: net.ParseIP(localIpAddr), // 指定你的本地IP地址
		//	}
		//
		//	start := time.Now()
		//
		//	r, _ := net.ResolveTCPAddr(network, addr)
		//
		//	var (
		//		localTCPConn *net.TCPConn
		//		err          error
		//	)
		//	defer func() {
		//		if proxyDebug {
		//			end := time.Now()
		//			log.Info(fmt.Sprintf("获取的IP代理信息(建立连接耗时:%v ) 代理池缓存的 ip 数量:%v %+v", end.Sub(start).String(), proxy.GetProxyCacheSize(), err))
		//		}
		//	}()
		//
		//	localTCPConn, err = net.DialTCP(network, localAddr, r)
		//	if err != nil {
		//		return nil, err
		//	}
		//
		//	_ = localTCPConn.SetKeepAlive(false)
		//	_ = localTCPConn.SetDeadline(time.Now().Add(workConfig.TransPortConfig.ConnTimeOut))
		//	_ = localTCPConn.SetWriteDeadline(time.Now().Add(workConfig.TransPortConfig.WriteTimeOut))
		//	_ = localTCPConn.SetReadDeadline(time.Now().Add(workConfig.TransPortConfig.ReadTimeOut))
		//	return localTCPConn, nil
		// }
		transport.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
			dialer := &net.Dialer{
				LocalAddr: &net.TCPAddr{
					IP: net.ParseIP(localIpAddr),
				},
				Timeout: workConfig.TransPortConfig.DialTimeOut,
			}

			start := time.Now()

			var (
				localConn net.Conn
				err       error
			)
			defer func() {
				if proxyDebug {
					end := time.Now()
					log.Info(fmt.Sprintf("获取的IP代理信息(建立连接耗时:%v ) 本地网卡信息(%v %v),代理池缓存的 ip 数量:%v %+v",
						end.Sub(start).String(),
						localIpAddr, network,
						proxy.GetProxyCacheSize(), err))
				}
			}()

			localConn, err = dialer.Dial(network, addr)
			if err != nil {
				return nil, err
			}

			_ = localConn.SetDeadline(time.Now().Add(workConfig.TransPortConfig.ConnTimeOut))
			_ = localConn.SetWriteDeadline(time.Now().Add(workConfig.TransPortConfig.WriteTimeOut))
			_ = localConn.SetReadDeadline(time.Now().Add(workConfig.TransPortConfig.ReadTimeOut))

			if _, ok := localConn.(*net.TCPConn); ok {
				_ = localConn.(*net.TCPConn).SetKeepAlive(true)
			}
			return localConn, nil
		}
	}

	var (
		err      error
		proxyUrl *url.URL
	)

	if proxyEnable {
		start := time.Now()
		proxyUrl, err = url.Parse(proxy.GetProxy(country))
		if err != nil {
			panic(err)
		}

		if proxyDebug {
			end := time.Now()
			log.Info(fmt.Sprintf("获取的IP代理信息(耗时:%v URL:%v) 代理池缓存的 ip 数量:%v", end.Sub(start).String(), proxyUrl, proxy.GetProxyCacheSize()))
		}

		transport.Proxy = http.ProxyURL(proxyUrl)
	}

	return transport, proxyUrl
}

// func SetDefaultTransport(country string) (http.RoundTripper, *url.URL) {
//
//	timeout := 15 * time.Second
//	n := &net.Dialer{
//		Timeout: timeout,
//	}
//
//	transport := &http.Transport{
//		DialContext:           n.DialContext,
//		IdleConnTimeout:       90 * time.Second,
//		ExpectContinueTimeout: 15 * time.Second,
//		TLSHandshakeTimeout:   15 * time.Second,
//		MaxIdleConns:          transConfig.MaxIdleConnCount,
//		MaxConnsPerHost:       transConfig.MaxConnCount,
//		MaxIdleConnsPerHost:   transConfig.MaxIdleConnCount,
//		//DisableKeepAlives:     true,
//	}
//
//	if len(localIpList) > 0 {
//
//		var (
//			localIpAddr = localIpList[rand.In(0, len(localIpList)-1)]
//		)
//
//		transport.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
//			localAddr := &net.TCPAddr{
//				IP: net.ParseIP(localIpAddr), // 指定你的本地IP地址
//			}
//
//			start := time.Now()
//
//			r, _ := net.ResolveTCPAddr(network, addr)
//
//			localTCPConn, err := net.DialTCP(network, localAddr, r)
//			if err != nil {
//				return nil, err
//			}
//
//			if proxyDebug {
//				end := time.Now()
//				log.Info(fmt.Sprintf("获取的IP代理信息(建立连接耗时:%v ) 代理池缓存的 ip 数量:%v", end.Sub(start).String(), GetProxyCacheSize()))
//			}
//
//			_ = localTCPConn.SetKeepAlive(false)
//			_ = localTCPConn.SetDeadline(time.Now().Add(15 * time.Second))
//			_ = localTCPConn.SetWriteDeadline(time.Now().Add(15 * time.Second))
//			_ = localTCPConn.SetReadDeadline(time.Now().Add(15 * time.Second))
//			return localTCPConn, nil
//		}
//	}
//
//	var (
//		err      error
//		proxyUrl *url.URL
//	)
//
//	if proxyEnable {
//		start := time.Now()
//		proxyUrl, err = url.Parse(GetProxy(country))
//		if err != nil {
//			panic(err)
//		}
//
//		if proxyDebug {
//			end := time.Now()
//			log.Info(fmt.Sprintf("获取的IP代理信息(耗时:%v URL:%v) 代理池缓存的 ip 数量:%v", end.Sub(start).String(), proxyUrl, GetProxyCacheSize()))
//		}
//
//		transport.Proxy = http.ProxyURL(proxyUrl)
//	}
//
//	return transport, proxyUrl
// }
